<template>
  <div class="container" ref="container">
    <div class="box"></div>
  </div>
</template>
<script setup lang="ts">
import * as THREE from 'three'
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'
// 引入性能监视器
import Stats from 'three/examples/jsm/libs/stats.module.js'
// 导入动画库
import gsap from 'gsap'
// 导入dat.gui
import * as dat from 'dat.gui'

import { onMounted, ref } from 'vue'
// import { RouterLink, RouterView } from 'vue-router'

const container: any = ref(null)
// 创建性能监视器
const stats = new (<any>Stats)()

// 创建场景
const scene = new THREE.Scene()
scene.background = new THREE.Color('rgb(0,47,167)')

// 创建相机
const camera = new THREE.PerspectiveCamera(
  100,
  window.innerWidth / (window.innerHeight - 1),
  0.1,
  1000
)
// 默认情况下，当我们调用scene.add()的时候，物体将会被添加到(0,0,0)坐标。
// 但将使得摄像机和立方体彼此在一起。为了防止这种情况的发生，我们只需要将摄像机稍微向外移动一些即可。
camera.position.set(0, 10, 100)

// 坐标网格
const gridHelper = new THREE.GridHelper(
  1000,
  100,
  new THREE.Color('#F7F7F7'),
  new THREE.Color('#F7F7F7')
)
scene.add(gridHelper)

// 创建渲染器
const renderer = new THREE.WebGLRenderer({
  precision: 'highp', //着色器精度
  antialias: true //抗锯齿
})
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight - 1)

// 轨道控制器
const orbitControls = new OrbitControls(camera, renderer.domElement)
orbitControls.update()

function animate() {
  group.rotation.y += Math.PI / 180
  requestAnimationFrame(animate)
  renderer.render(scene, camera)
  stats.update()
  orbitControls.update()
}

// 画面尺寸变化
window.addEventListener('resize', () => {
  console.log('尺寸变化')
  // 摄像机视锥体的长宽比，通常是使用画布的宽/画布的高。默认值是1（正方形画布）。
  camera.aspect = window.innerWidth / (window.innerHeight - 1)
  camera.updateProjectionMatrix()
  //渲染器宽高比
  renderer.setSize(window.innerWidth, window.innerHeight - 1)
  renderer.setPixelRatio(window.devicePixelRatio)
})

// 创建辅助坐标
const axesHelper = new THREE.AxesHelper(20)
scene.add(axesHelper)

// 1、创建一个矩形
const boxGeometry = new THREE.BoxGeometry(10, 10, 10, 2, 2) //(,,细分数,细分数)
//  2、创建材质
const material = new THREE.MeshBasicMaterial({
  color: 0xff00ff,
  wireframe: true
})
// 3、创建网格对象
const boxMesh = new THREE.Mesh(boxGeometry, material)
boxMesh.name = '矩形'
boxMesh.position.x = 10
// boxMesh.rotateY(Math.PI / 4)
// 4、添加到场景中
// scene.add(boxMesh)

// 创建一个球
const sphereGeometry = new THREE.SphereGeometry(15, 8, 8) //后两个参数是细分数，过小会导致不够圆，默认(,32,16)
const sphereMesh = new THREE.Mesh(sphereGeometry, material)
sphereMesh.name = '球'
sphereMesh.position.x = 40
// scene.add(sphereMesh)

/**
 *  可以创建一个组，通过组一次性添加
 *  对组进行旋转、平移、缩放等操作，会同时修改组内所有模型的属性
 */
const group = new THREE.Group()
group.add(boxMesh, sphereMesh)
// group.rotateY(Math.PI / 4)
group.translateY(40)
group.scale.set(2, 2, 2)
scene.add(group)

// 沿着自定义方向移动
const axis = new THREE.Vector3(1, 1, 1)
// 向量归一化(具体就是将向量转为单位为1的一个方向)
axis.normalize()
// 沿着axis表示的方向平移
group.translateOnAxis(axis, 100)

console.log(scene.children) //查看子对象

// 欧拉对象Euler
const Euler = new THREE.Euler(0, Math.PI / 4, 0)
group.setRotationFromEuler(Euler) //等价于group.rotateY(Math.PI / 4)

// 页面挂载后渲染
onMounted(() => {
  console.log(container.value)
  container.value?.appendChild(renderer.domElement)
  container.value?.appendChild(stats.domElement) //性能监视器
  animate()
})
</script>
<style scoped>
.box {
  width: 100px;
  height: 100px;
  position: absolute;
}
</style>
